<!-- @format -->

<template>
  <view
    class="comp-checkbox"
    :class="[
      { 'comp-checkbox--checked': isChecked },
      { 'comp-checkbox--disabled': disabled },
      { 'comp-checkbox--indeterminate': indeterminate },
      { 'comp-checkbox--bordered': bordered },
      { 'comp-checkbox--button': button },
      { 'comp-checkbox--with-label': label || $slots.default },
      `comp-checkbox--${size}`,
    ]"
    @click="handleClick"
  >
    <!-- 复选框图标 -->
    <view v-if="!button" class="comp-checkbox__icon-wrap">
      <view
        class="comp-checkbox__icon"
        :style="{
          borderColor: checkedColor,
          backgroundColor: isChecked ? checkedColor : '',
        }"
      >
        <view
          v-if="isChecked && !indeterminate"
          class="comp-checkbox__check"
        ></view>
        <view v-if="indeterminate" class="comp-checkbox__indeterminate"></view>
      </view>
    </view>

    <!-- 标签内容 -->
    <view v-if="label || $slots.default" class="comp-checkbox__label">
      <slot>{{ label }}</slot>
    </view>
  </view>
</template>

<script setup lang="ts">
  import { computed, ref, watch, inject, getCurrentInstance } from 'vue';

  // 定义复选框属性
  interface Props {
    /** 是否选中 */
    modelValue?: boolean;
    /** 复选框的值，用于组合使用 */
    value?: string | number | boolean;
    /** 是否禁用 */
    disabled?: boolean;
    /** 复选框标签 */
    label?: string;
    /** 选中状态的颜色 */
    checkedColor?: string;
    /** 是否为半选状态 */
    indeterminate?: boolean;
    /** 尺寸大小 */
    size?: 'small' | 'medium' | 'large';
    /** 是否显示边框 */
    bordered?: boolean;
    /** 是否为按钮样式 */
    button?: boolean;
    /** 复选框名称，用于表单提交 */
    name?: string;
  }

  // 定义默认属性
  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    value: '',
    disabled: false,
    label: '',
    checkedColor: '#1989fa',
    indeterminate: false,
    size: 'medium',
    bordered: false,
    button: false,
    name: '',
  });

  // 定义事件
  const emit = defineEmits<{
    /** 更新选中状态 */
    (e: 'update:modelValue', value: boolean): void;
    /** 变更事件 */
    (e: 'change', value: boolean): void;
    /** 点击事件 */
    (e: 'click', event: Event): void;
  }>();

  // 获取复选框组上下文
  const checkboxGroup = inject<{
    props: {
      modelValue: (string | number | boolean)[];
      disabled?: boolean;
      max?: number;
    };
    toggle: (value: string | number | boolean) => void;
    isValueChecked: (value: string | number | boolean) => boolean;
    isMaxLimitReached: () => boolean;
  } | null>('checkboxGroup', null);

  // 计算是否选中
  const isChecked = computed(() => {
    if (checkboxGroup) {
      return checkboxGroup.isValueChecked(props.value);
    }
    return props.modelValue;
  });

  // 计算是否禁用
  const isDisabled = computed(() => {
    if (checkboxGroup) {
      // 如果组禁用或达到最大选择数量且当前未选中，则禁用
      const maxLimitReached = checkboxGroup.isMaxLimitReached();
      return (
        props.disabled ||
        checkboxGroup.props.disabled ||
        (maxLimitReached && !isChecked.value)
      );
    }
    return props.disabled;
  });

  // 处理点击事件
  const handleClick = (event: Event) => {
    if (isDisabled.value) {
      return;
    }

    const newValue = !isChecked.value;

    if (checkboxGroup) {
      checkboxGroup.toggle(props.value);
    } else {
      emit('update:modelValue', newValue);
    }

    emit('change', newValue);
    emit('click', event);
  };

  // 暴露方法
  defineExpose({
    /** 获取当前选中状态 */
    isChecked: () => isChecked.value,
    /** 设置选中状态 */
    setChecked: (checked: boolean) => {
      if (!isDisabled.value) {
        if (checkboxGroup) {
          if (checked !== isChecked.value) {
            checkboxGroup.toggle(props.value);
          }
        } else {
          emit('update:modelValue', checked);
          emit('change', checked);
        }
      }
    },
    /** 切换选中状态 */
    toggle: () => {
      if (!isDisabled.value) {
        handleClick(new Event('click'));
      }
    },
  });
</script>

<style lang="scss">
  .comp-checkbox {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
    margin-right: 16px;
    font-size: 14px;
    line-height: 1.5;
    color: #323233;

    &__icon-wrap {
      display: flex;
      align-items: center;
      justify-content: center;
      margin-right: 8px;
    }

    &__icon {
      position: relative;
      box-sizing: border-box;
      width: 20px;
      height: 20px;
      border: 1px solid #c8c9cc;
      border-radius: 2px;
      transition: all 0.2s;
    }

    &__check {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 10px;
      height: 6px;
      border: 2px solid #fff;
      border-top: 0;
      border-right: 0;
      transform: translate(-50%, -60%) rotate(-45deg);
    }

    &__indeterminate {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 10px;
      height: 2px;
      background-color: #fff;
      transform: translate(-50%, -50%);
    }

    &__label {
      color: #323233;
    }

    // 选中状态
    &--checked {
      .comp-checkbox__icon {
        background-color: #1989fa;
        border-color: #1989fa;
      }
    }

    // 禁用状态
    &--disabled {
      cursor: not-allowed;
      opacity: 0.6;

      .comp-checkbox__label {
        color: #c8c9cc;
      }
    }

    // 带边框样式
    &--bordered {
      padding: 8px 12px;
      border: 1px solid #dcdee0;
      border-radius: 4px;

      &.comp-checkbox--checked {
        border-color: #1989fa;
      }
    }

    // 按钮样式
    &--button {
      margin-right: 0;
      padding: 8px 16px;
      border: 1px solid #dcdee0;
      border-radius: 0;
      background-color: #fff;
      transition: all 0.2s;

      &:first-child {
        border-radius: 4px 0 0 4px;
      }

      &:last-child {
        border-radius: 0 4px 4px 0;
      }

      &:not(:first-child) {
        margin-left: -1px;
      }

      &.comp-checkbox--checked {
        color: #fff;
        background-color: #1989fa;
        border-color: #1989fa;
        z-index: 1;
      }
    }

    // 尺寸变体
    &--small {
      font-size: 12px;

      .comp-checkbox__icon {
        width: 16px;
        height: 16px;
      }

      .comp-checkbox__check {
        width: 8px;
        height: 5px;
      }

      &.comp-checkbox--button {
        padding: 6px 12px;
      }
    }

    &--large {
      font-size: 16px;

      .comp-checkbox__icon {
        width: 24px;
        height: 24px;
      }

      .comp-checkbox__check {
        width: 12px;
        height: 7px;
      }

      &.comp-checkbox--button {
        padding: 10px 20px;
      }
    }
  }
</style>
